#include "es_iic.h"

//iic初始化
void iic_init(u16 my_addr,u32 iicSpeed){
    //开启iic外设时钟
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C,ENABLE);

    //重置iic
    I2C_DeInit();

    //初始化iic,16M cpu频率，7位地址,当前位ack
    I2C_Init(iicSpeed, my_addr, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);

    //启用iic
    I2C_Cmd(ENABLE);
}




/*
主机模式-发送数据

slaveAddr:目标地址(7bit)
buf:字节缓存起始地址
len:缓存长度
*/
void iic_master_write(u8 slaveAddr,u8* wBuf,int wLen){
    int i=0;

    //等待总线
    iic_waitBus();

    //开启ACK
    I2C_AcknowledgeConfig(I2C_ACK_CURR);

    //建立开始信号
    I2C_GenerateSTART(ENABLE);
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));      //等待EV5 (主机模式选择)

    //发送从机地址(方向为发送)
    I2C_Send7bitAddress(slaveAddr,I2C_DIRECTION_TX);        //发送方向
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //等待EV6 (主机发送模式已选中)

    //发送数据
    for(i=0;i<wLen;i++){
        I2C_SendData(wBuf[i]);
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待EV8 (数据已发送)
    }

    //建立停止信号
    I2C_GenerateSTOP(ENABLE);
}





/*
主机模式-先发送数据，然后读取数据

slaveAddr:目标地址
wBuf:wirte缓存
wLen:wirte长度
rBuf:read缓存
rLen:read长度
*/
void iic_master_write_read(u8 slaveAddr,u8* wBuf,int wLen,u8* rBuf,int rLen){
    int i=0;
    int ptr=0;
    
    //等待总线
    iic_waitBus();

    //开启ACK
    I2C_AcknowledgeConfig(I2C_ACK_CURR);

    //建立开始信号
    I2C_GenerateSTART(ENABLE);
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));      //等待EV5 (主机模式选择)
    
    //发送从机地址(方向为发送)
    I2C_Send7bitAddress(slaveAddr,I2C_DIRECTION_TX);        //发送方向
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //等待EV6 (主机发送模式已选中)

    //发送数据
    for(i=0;i<wLen;i++){
        I2C_SendData(wBuf[i]);
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)); //等待EV8 (数据已发送)
    }



    //转为主机接收模式,不需要STOP。直接重新START
    I2C_GenerateSTART(ENABLE);
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)); //等待EV5 (主机模式选择)

    //发送从机地址
    I2C_Send7bitAddress(slaveAddr,I2C_DIRECTION_RX); //接收方向
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //等待EV6 (主机接收模式选中)


    //接收rLen-1个byte （最后1byte要stop后再接收）   
    for(i=0;i<rLen-1;i++){
        //等待EV7 (主机-数据已接收)
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); 		
        rBuf[ptr++] = I2C_ReceiveData(); 		//从I2C寄存器读取接收到的值
    }

    //接收最后1byte之前，关闭ack及建立stop
    //关闭ACK
    I2C_AcknowledgeConfig(I2C_ACK_NONE);    

    //建立停止信号
	I2C_GenerateSTOP(ENABLE); 

    //接收最后1byte
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); //等待EV7 (主机-数据已接收)
    rBuf[ptr++] = I2C_ReceiveData(); 		//从I2C寄存器读取接收到的值
}




/*
主机读取模式

slaveAddr:目标地址
rBuf:read缓存
rLen:read长度
*/
void iic_master_read(u8 slaveAddr,u8* rBuf,int rLen){
    int i=0;
    int ptr=0;

    //等待总线
    iic_waitBus();

    //开启ACK
    I2C_AcknowledgeConfig(I2C_ACK_CURR);

    //建立开始信号
    I2C_GenerateSTART(ENABLE);
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));      //等待EV5 (主机模式选择)

    //发送从机地址
    I2C_Send7bitAddress(slaveAddr,I2C_DIRECTION_RX); //接收方向
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); //等待EV6 (主机接收模式选中)

    //接收rLen-1个byte （最后1byte要stop后再接收）   
    for(i=0;i<rLen-1;i++){
        //等待EV7 (主机-数据已接收)
        while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); 		
        rBuf[ptr++] = I2C_ReceiveData(); 		//从I2C寄存器读取接收到的值
    }

    //接收最后1byte之前，关闭ack及建立stop
    //关闭ACK
    I2C_AcknowledgeConfig(I2C_ACK_NONE);    

    //建立停止信号
	I2C_GenerateSTOP(ENABLE); 

    //接收最后1byte
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED)); //等待EV7 (主机-数据已接收)
    rBuf[ptr++] = I2C_ReceiveData(); 		//从I2C寄存器读取接收到的值
}





//写地址寄存器
void iic_master_write_reg(u8 slaveAddr, u8 reg, u8 data){    
    u8 txdata[2];
    txdata[0]=reg;
    txdata[1]=data;
			
    iic_master_write(slaveAddr, txdata, 2);    
}


//读取地址寄存器
void iic_master_read_reg(u8 slaveAddr,u8 reg, u8* data){
    iic_master_write_read(slaveAddr, &reg, 1, data, 1);	
}




void iic_waitBus(){
    while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); 		
}



